using Godot;
using Godot.Collections;
using System;
using System.Collections.Generic;
using Array = Godot.Collections.Array;
//待重置
public class Store
{
    public int[] input = null;
    public int[] output = null;
    public int[] fuel = null;
    public int[] store = null;
    public int Size = 27;
    public int Max = 27;
    public ItemStack[] Items;
    public bool Updata = true;
    public Store(int s)
    {
        Size = s;
        Max = Size;
        Items = new ItemStack[Size];
    }
    public void SetMax(int max)
    {
        this.Max = max;
    }
    public bool MergetItem(int index, ItemStack item)
    {
        if (CanMerge(index, item))
        {
            ItemStack i = GetItemStack(index);
            if (i == null)
            {
                SetItem(index, item.Copy());
            }
            else
            {
                AddAmount(index, item.Amount);
            }
            return true;
        }
        return false;
    }
    public bool CanMerge(int index, ItemStack item)
    {
        ItemStack i = GetItemStack(index);
        if (i == null) return true;

        if (i.equalMaterial(item))
        {
            if (i.Amount + item.Amount <= i.getMaterial().MaxAmount)
            {
                return true;
            }
            return false;
        }
        else
        {
            return false;
        }
    }
    public void AddItems(List<ItemStack> items)
    {
        for (int i = 0; i < items.Count; i++)
        {
            AddItem(items[i].Copy());
        }
    }
    public bool AddItem(ItemStack Target, int[] array)
    {
        if (Target.Name == "air")
        {
            return false;
        }


        Updata = true;
        foreach (int i in array)
        {
            if (Items[i] == null)
            {
                Items[i] = Target;
                return true;
            }
            else
            {
                ItemStack Item = (ItemStack)Items[i];
                if (Item.Name == Target.Name)
                {
                    if (!Item.IsFull())
                    {
                        int last = Item.getLastAmount();
                        if (last >= Target.Amount)
                        {
                            Item.Amount += Target.Amount;
                            Target = null;
                            return true;
                        }
                        else
                        {
                            Target.Amount -= Item.Amount;
                            Item.Amount = Item.getMaterial().MaxAmount;
                        }
                    }
                }
            }
        }
        return false;
    }
    public bool CanAddItem(ItemStack Target)
    {
        ItemStack item = Target.Copy();
        for (int i = 0; i < Max; i++)
        {
            if (Items[i] == null) return true;
            if (Items[i].equalMaterial(item))
            {
                if (item.Amount + Items[i].Amount <= item.getMaterial().MaxAmount)
                {
                    return true;
                }
                else
                {
                    item.Amount -= item.getMaterial().MaxAmount - Items[i].Amount;
                }
            }
        }
        return false;
    }
    public bool CanAddItem(ItemStack Target, int[] array)
    {
        ItemStack item = Target.Copy();
        foreach (int i in array)
        {
            if (Items[i] == null) return true;
            if (Items[i].equalMaterial(item))
            {
                if (item.Amount + Items[i].Amount <= item.getMaterial().MaxAmount)
                {
                    return true;
                }
                else
                {
                    item.Amount -= item.getMaterial().MaxAmount - Items[i].Amount;
                }
            }
        }
        return false;
    }
    public bool AddItem(ItemStack Target, int start = 0)
    {
        if (
            Target.Name == null ||
            Target.Name == "air" ||
            Target.Name == "null"
            )
        {
            return false;
        }


        Updata = true;
        for (int i = start; i < Max; i++)
        {
            if (Items[i] == null)
            {
                Items[i] = Target;
                return true;
            }
            else
            {
                ItemStack Item = (ItemStack)Items[i];
                if (Item.Name == Target.Name)
                {
                    if (!Item.IsFull())
                    {
                        int last = Item.getLastAmount();
                        if (last >= Target.Amount)
                        {
                            Item.Amount += Target.Amount;
                            Target = null;
                            return true;
                        }
                        else
                        {
                            Target.Amount -= Item.getLastAmount();
                            Item.Amount = Item.getMaterial().MaxAmount;
                        }
                    }
                }
            }
        }
        return false;
    }
    public ItemStack GetItemStack(int index)
    {
        Updata = true;
        if (index >= Size || index > Items.Length)
        {
            return null;
        }
        return Items[index];
    }
    public void SetItem(int index, ItemStack item)
    {
        Updata = true;
        Items[index] = item;
    }
    public void Remove(int index)
    {
        Updata = true;
        Items[index] = null;
    }
    public void SetAmount(int index, int amount)
    {
        Updata = true;
        Items[index] = Items[index].SetAmount(amount);
    }
    //减少数量并返回还有多少没减少.
    public int SubAmount(int index, int amount = 1)
    {
        Updata = true;
        if (Items[index] != null)
        {
            Items[index].Amount -= amount;

            if (Items[index].Amount <= 0)
            {
                int a = Math.Abs(Items[index].Amount);
                Items[index] = null;
                return a;
            }
            else if (Items[index].itemData != null) Items[index].itemData = Items[index].getMaterial().GetItemData();
        }
        return 0;
    }
    //增加并返回还有多少没添加
    public int AddAmount(int index, int amount = 1)
    {
        Updata = true;
        if (Items[index] != null)
        {
            Items[index].Amount += amount;
            if (Items[index].Amount > Items[index].getMaterial().MaxAmount)
            {
                int a = Items[index].Amount - Items[index].getMaterial().MaxAmount;
                Items[index].Amount = Items[index].getMaterial().MaxAmount;
                return a;
            }
        }
        return 0;
    }


    public void QuikToStore(int index)
    {
        Updata = true;
        ItemStack item = GetItemStack(index);
        if (item == null) return;
        if (index < 9)
        {
            if (AddItem(item, 9)) SetItem(index, null);
        }
        else
        {
            if (AddItem(item)) SetItem(index, null);
        }


    }


    public Dictionary getDict()
    {
        Array array = new Array();
        for (int i = 0; i < Size; i++)
        {
            if (Items[i] != null)
            {
                array.Add(Items[i].getDict());
            }
            else
            {
                array.Add("null");
            }
        }
        Dictionary dict = new Dictionary();
        dict.Add("Size", Size);

        dict.Add("Items", array);
        return dict;
    }
    public String toJson()
    {
        return JSON.Print(getDict());
    }
    public Store JsonTo(Dictionary dict)
    {
        Size = dict["Size"].ToInt();
        Array array = (Array)dict["Items"];
        Items = new ItemStack[Size];
        for (int index = 0; index < array.Count; index++)
        {
            if (array[index] is String)
            {
                Items[index] = null;
            }
            else
            {
                Dictionary id = (Dictionary)array[index];
                ItemStack item = new ItemStack().JsonTo(id);
                SetItem(index,item);
                //AddItem(item);
            }

        }
        return this;
    }
}